/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/*!
 * @file ac780x_crc.c
 *
 * @brief This file provides CRC integration functions.
 *
 */

/* ===========================================  Includes  =========================================== */
#include "ac780x_crc_reg.h"

/* ============================================  Define  ============================================ */

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */
/* save user defined CRC_WriteBytesNumOnceType option  */
static CRC_WriteBytesNumOnceType s_crcWriteBytesNumOnce = CRC_WRITE_1_BYTE_ONCE;

/* ====================================  Functions declaration  ===================================== */

/* ======================================  Functions define  ======================================== */
/*!
 * @brief Initialize CRC module.
 *
 * @param[in] config: CRC configuration pointer
 * @return none
 */
void CRC_Init(const CRC_ConfigType *config)
{
    DEVICE_ASSERT(NULL != config);

    /* enable CRC system module */
    CKGEN_Enable(CLK_CRC, ENABLE);
    CKGEN_SoftReset(SRST_CRC, ENABLE);

    /* config CRC ProtocolType firstly */
    CRC_SetProtocolType(config->crcProtocolType);

    /* config CRC misc */
    CRC_SetWriteTranspose(config->writeTransposeType);
    CRC_SetReadTranspose(config->readTransposeType);
    CRC_SetResultXorMode(config->finalXOR);
    CRC_SetPolyReg(config->poly);
    s_crcWriteBytesNumOnce = config->writeBytesNumOnce;
}

/*!
 * @brief CRC De-initialize.
 *
 * @param[in] none
 * @return none
 */
void CRC_DeInit(void)
{
    CKGEN_SoftReset(SRST_CRC, DISABLE);
    CKGEN_Enable(CLK_CRC, DISABLE);
}

/*!
 * @brief excute CRC check.
 *
 * @param[in] seed: load CRC seed value
 * @param[in] msg: pointer to the data array
 * @param[in] sizeBytes: number of the data array
 * @return result: the CRC result
 */
uint32_t CRC_Check(uint32_t seed, const uint8_t *msg, uint32_t sizeBytes)
{
    uint32_t i = 0U, j = 0U;
    uint32_t sizeWords = 0U, sizeDWords = 0U;
    uint32_t result = 0U;

    sizeWords = sizeBytes >> 1U;
    sizeDWords = sizeBytes >> 2U;

    CRC_SetSeedOrDataMode(CRC_DATA_IS_SEED);
    CRC_SetDataReg(seed);
    CRC_SetSeedOrDataMode(CRC_DATA_IS_DATA);

    switch (s_crcWriteBytesNumOnce)
    {
    case CRC_WRITE_1_BYTE_ONCE:
        for (i = 0U; i < sizeBytes; i++)
        {
            CRC_SetDataLLReg(msg[i]);
        }
        break;

    case CRC_WRITE_2_BYTE_ONCE:
        for (i = 0U; i < sizeWords; i++)
        {
            CRC_SetDataLReg((((uint16_t)msg[j] << 8U) | ((uint16_t)msg[j + 1U])));
            j += 2U;
        }
        for (; j < sizeBytes; j++)
        {
            CRC_SetDataLLReg(msg[j]);
        }
        break;

    case CRC_WRITE_4_BYTE_ONCE:
        for (i = 0U, j = 0U; i < sizeDWords; i++)
        {
            CRC_SetDataReg((((uint32_t)msg[j] << 24U) | ((uint32_t)msg[j + 1U] << 16U) | ((uint32_t)msg[j + 2U] << 8U) | ((uint32_t)msg[j + 3U])));
            j += 4U;
        }
        if (2U <= (sizeBytes - j))
        {
            CRC_SetDataLReg((((uint16_t)msg[j] << 8U) | ((uint16_t)msg[j + 1U])));
            j += 2U;
        }
        for (; j < sizeBytes; j++)
        {
            CRC_SetDataLLReg(msg[j]);
        }
        break;

    default:
        break;
    }

    result = CRC_GetDataReg();
    result = (CRC_PROTOCOL_32BIT == CRC_GetProtocolType()) ? result : ((uint16_t)result);

    return result;
}

/* =============================================  EOF  ============================================== */
